{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# 03 langchain 提示词\n",
    "https://python.langchain.com/docs/modules/model_io/prompts/"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "任何语言模型应用程序的核心元素都是...模型。\n",
    "LangChain为您提供了与任何语言模型交互的构建块。\n",
    "Prompts：模板化、动态选择和管理模型输入\n",
    "语言模型：通过通用接口调用语言模型\n",
    "输出解析器：从模型输出中提取信息\n",
    "<img src=\"https://python.langchain.com/assets/images/model_io-1f23a36233d7731e93576d6885da2750.jpg\" alt=\"图片\" width=\"900\" height=\"500\">\n",
    "\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1 Prompts\n",
    "语言模型提示是用户提供的一组指令或输入，用于指导模型的响应，帮助它理解上下文并生成相关且连贯的基于语言的输出，例如回答问题、完成句子或参与对话。\n",
    "LangChain 提供了多个类和函数来帮助构造和使用提示。\n",
    "提示模板：参数化模型输入\n",
    "示例选择器：动态选择要包含在提示中的示例"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 3.1.1 PromptTemplate\n",
    "提示模板是为语言模型生成提示的预定义配方。\n",
    "模板可能包括说明、几个镜头示例以及适合给定任务的特定上下文和问题。\n",
    "LangChain 提供了创建和使用提示模板的工具。\n",
    "LangChain 致力于创建与模型无关的模板，以便轻松地跨不同语言模型重用现有模板。\n",
    "通常，语言模型希望提示是字符串或聊天消息列表。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "data": {
      "text/plain": "'Tell me a funny joke about chickens.'"
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain import PromptTemplate #用于 PromptTemplate 为字符串提示创建模板。\n",
    "\n",
    "#默认情况下， PromptTemplate 使用 Python 的 str.format 语法进行模板化;但是可以使用其他模板语法（例如， jinja2 ）\n",
    "prompt_template = PromptTemplate.from_template(\n",
    "    \"Tell me a {adjective} joke about {content}.\"\n",
    ")\n",
    "prompt_template.format(adjective=\"funny\", content=\"chickens\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-08T22:58:30.158244Z",
     "end_time": "2023-08-08T22:58:42.102618Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "data": {
      "text/plain": "'Tell me a joke'"
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain import PromptTemplate\n",
    "\n",
    "prompt_template = PromptTemplate.from_template(\n",
    "\"Tell me a joke\"\n",
    ")\n",
    "prompt_template.format()#该模板支持任意数量的变量，包括无变量："
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-08T22:59:17.844102Z",
     "end_time": "2023-08-08T22:59:17.864313Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "ename": "ValidationError",
     "evalue": "1 validation error for PromptTemplate\n__root__\n  Invalid prompt schema; check for mismatched or missing input parameters. 'content' (type=value_error)",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mValidationError\u001B[0m                           Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[3], line 5\u001B[0m\n\u001B[0;32m      1\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mlangchain\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m PromptTemplate\n\u001B[0;32m      3\u001B[0m \u001B[38;5;66;03m#对于其他验证，请显式指定 input_variables 。\u001B[39;00m\n\u001B[0;32m      4\u001B[0m \u001B[38;5;66;03m#在实例化期间，这些变量将与模板字符串中存在的变量进行比较，如果不匹配，则会引发异常;\u001B[39;00m\n\u001B[1;32m----> 5\u001B[0m invalid_prompt \u001B[38;5;241m=\u001B[39m \u001B[43mPromptTemplate\u001B[49m\u001B[43m(\u001B[49m\n\u001B[0;32m      6\u001B[0m \u001B[43m    \u001B[49m\u001B[43minput_variables\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43m[\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43madjective\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m      7\u001B[0m \u001B[43m    \u001B[49m\u001B[43mtemplate\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mTell me a \u001B[39;49m\u001B[38;5;132;43;01m{adjective}\u001B[39;49;00m\u001B[38;5;124;43m joke about \u001B[39;49m\u001B[38;5;132;43;01m{content}\u001B[39;49;00m\u001B[38;5;124;43m.\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\n\u001B[0;32m      8\u001B[0m \u001B[43m)\u001B[49m\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\load\\serializable.py:74\u001B[0m, in \u001B[0;36mSerializable.__init__\u001B[1;34m(self, **kwargs)\u001B[0m\n\u001B[0;32m     73\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21m__init__\u001B[39m(\u001B[38;5;28mself\u001B[39m, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Any) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[1;32m---> 74\u001B[0m     \u001B[38;5;28msuper\u001B[39m()\u001B[38;5;241m.\u001B[39m\u001B[38;5;21m__init__\u001B[39m(\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[0;32m     75\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_lc_kwargs \u001B[38;5;241m=\u001B[39m kwargs\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\pydantic\\main.py:341\u001B[0m, in \u001B[0;36mpydantic.main.BaseModel.__init__\u001B[1;34m()\u001B[0m\n",
      "\u001B[1;31mValidationError\u001B[0m: 1 validation error for PromptTemplate\n__root__\n  Invalid prompt schema; check for mismatched or missing input parameters. 'content' (type=value_error)"
     ]
    }
   ],
   "source": [
    "from langchain import PromptTemplate\n",
    "\n",
    "#对于其他验证，请显式指定 input_variables 。\n",
    "#在实例化期间，这些变量将与模板字符串中存在的变量进行比较，如果不匹配，则会引发异常;\n",
    "invalid_prompt = PromptTemplate(\n",
    "    input_variables=[\"adjective\"],\n",
    "    template=\"Tell me a {adjective} joke about {content}.\"\n",
    ")"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "data": {
      "text/plain": "[SystemMessage(content='You are a helpful AI bot. Your name is Bob.', additional_kwargs={}),\n HumanMessage(content='Hello, how are you doing?', additional_kwargs={}, example=False),\n AIMessage(content=\"I'm doing well, thanks!\", additional_kwargs={}, example=False),\n HumanMessage(content='What is your name?', additional_kwargs={}, example=False)]"
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#聊天模型的提示是聊天消息列表。\n",
    "#每条聊天消息都与内容相关联，以及一个名为 role 的附加参数。例如，在 OpenAI 聊天完成 API 中，聊天消息可以与 AI 助手、人员或系统角色相关联。\n",
    "\n",
    "from langchain.prompts import ChatPromptTemplate\n",
    "\n",
    "#ChatPromptTemplate.from_messages 接受各种消息表示形式。\n",
    "template = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"You are a helpful AI bot. Your name is {name}.\"),\n",
    "    (\"human\", \"Hello, how are you doing?\"),\n",
    "    (\"ai\", \"I'm doing well, thanks!\"),\n",
    "    (\"human\", \"{user_input}\"),\n",
    "])\n",
    "\n",
    "messages = template.format_messages(\n",
    "    name=\"Bob\",\n",
    "    user_input=\"What is your name?\"\n",
    ")\n",
    "messages"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-08T23:03:22.439209Z",
     "end_time": "2023-08-08T23:03:22.468210Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "data": {
      "text/plain": "AIMessage(content='I absolutely love indulging in mouthwatering delicacies!', additional_kwargs={}, example=False)"
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#除了使用上一个代码块中使用的（类型、内容）的 2 元组表示形式外，\n",
    "#您还可以传入 or BaseMessage 的 MessagePromptTemplate 实例。\n",
    "from langchain.prompts import ChatPromptTemplate\n",
    "from langchain.prompts.chat import SystemMessage, HumanMessagePromptTemplate\n",
    "\n",
    "template = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        SystemMessage(\n",
    "            content=(\n",
    "                \"You are a helpful assistant that re-writes the user's text to \"\n",
    "                \"sound more upbeat.\"\n",
    "            )\n",
    "        ),\n",
    "        HumanMessagePromptTemplate.from_template(\"{text}\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "\n",
    "#设置代理\n",
    "import os\n",
    "os.environ['http_proxy'] = 'http://127.0.0.1:10809'\n",
    "os.environ['https_proxy'] = 'http://127.0.0.1:10809'\n",
    "\n",
    "llm = ChatOpenAI()\n",
    "llm(template.format_messages(text='i dont like eating tasty things.'))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-08T23:04:36.780785Z",
     "end_time": "2023-08-08T23:04:38.785967Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 3.1.2 自定义提示模板\n",
    "LangChain 提供了一组默认的提示模板，可用于为各种任务生成提示。但是，在某些情况下，默认提示模板可能无法满足您的需求。例如，您可能希望创建一个提示模板，其中包含语言模型的特定动态说明。在这种情况下，您可以创建自定义提示模板。\n",
    "\n",
    "假设我们希望LLM生成给定名称的函数的英语解释。为了完成此任务，我们将创建一个自定义提示模板，该模板将函数名称作为输入，并格式化提示模板以提供函数的源代码。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "import inspect\n",
    "\n",
    "#我们将创建一个自定义提示模板，该模板将函数名称作为输入，并设置提示格式以提供函数的源代码。为了实现这一点，让我们首先创建一个函数，该函数将返回给定其名称的函数的源代码。\n",
    "def get_source_code(function_name):\n",
    "    # Get the source code of the function\n",
    "    return inspect.getsource(function_name)\n",
    "\n",
    "def test_add():\n",
    "    return 1 + 1"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-08T23:38:59.040271Z",
     "end_time": "2023-08-08T23:38:59.065778Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [],
   "source": [
    "from langchain.prompts import StringPromptTemplate\n",
    "from pydantic import BaseModel, validator\n",
    "\n",
    "PROMPT = \"\"\"\\\n",
    "Given the function name and source code, generate an English language explanation of the function.\n",
    "Function Name: {function_name}\n",
    "Source Code:\n",
    "{source_code}\n",
    "Explanation:\n",
    "\"\"\"\n",
    "\n",
    "\n",
    "class FunctionExplainerPromptTemplate(StringPromptTemplate, BaseModel):\n",
    "    \"\"\"A custom prompt template that takes in the function name as input, and formats the prompt template to provide the source code of the function.\"\"\"\n",
    "\n",
    "    @validator(\"input_variables\")\n",
    "    def validate_input_variables(cls, v):\n",
    "        \"\"\"Validate that the input variables are correct.\"\"\"\n",
    "        if len(v) != 1 or \"function_name\" not in v:\n",
    "            raise ValueError(\"function_name must be the only input_variable.\")\n",
    "        return v\n",
    "\n",
    "    def format(self, **kwargs) -> str:\n",
    "        # Get the source code of the function\n",
    "        source_code = get_source_code(kwargs[\"function_name\"])\n",
    "\n",
    "        # Generate the prompt to be sent to the language model\n",
    "        prompt = PROMPT.format(\n",
    "            function_name=kwargs[\"function_name\"].__name__, source_code=source_code\n",
    "        )\n",
    "        return prompt\n",
    "\n",
    "    def _prompt_type(self):\n",
    "        return \"function-explainer\""
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-08T23:39:13.550899Z",
     "end_time": "2023-08-08T23:39:13.590456Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Given the function name and source code, generate an English language explanation of the function.\n",
      "Function Name: test_add\n",
      "Source Code:\n",
      "def test_add():\n",
      "    return 1 + 1\n",
      "\n",
      "Explanation:\n",
      "\n"
     ]
    }
   ],
   "source": [
    "fn_explainer = FunctionExplainerPromptTemplate(input_variables=[\"function_name\"])\n",
    "\n",
    "# Generate a prompt for the function \"test_add\"\n",
    "prompt_1 = fn_explainer.format(function_name=test_add)\n",
    "print(prompt_1)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-08T23:49:06.883983Z",
     "end_time": "2023-08-08T23:49:06.944051Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "outputs": [
    {
     "data": {
      "text/plain": "'The function \"test_add\" takes no input parameters and returns the result of adding 1 and 1 together.'"
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain import LLMChain\n",
    "chat_prompt = ChatPromptTemplate.from_messages([prompt_1])\n",
    "chain = LLMChain(\n",
    "    llm=ChatOpenAI(),\n",
    "    prompt=chat_prompt\n",
    ")\n",
    "chain.run({})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-08T23:49:07.867760Z",
     "end_time": "2023-08-08T23:49:09.562415Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1.3 带例子的提示词模板\n",
    "\n",
    "我们在写提示词模板的时候，有些情况下，我们需要给出一些例子，这样可以让模型更好的理解我们的意图。\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [],
   "source": [
    "from langchain.prompts.few_shot import FewShotPromptTemplate\n",
    "from langchain.prompts.prompt import PromptTemplate\n",
    "\n",
    "#这里我们用字典来表示一个例子，每个示例都应该是一个字典，其中键是输入变量，值是这些输入变量的值。\n",
    "examples = [\n",
    "  {\n",
    "    \"question\": \"Who lived longer, Muhammad Ali or Alan Turing?\",\n",
    "    \"answer\":\n",
    "\"\"\"\n",
    "Are follow up questions needed here: Yes.\n",
    "Follow up: How old was Muhammad Ali when he died?\n",
    "Intermediate answer: Muhammad Ali was 74 years old when he died.\n",
    "Follow up: How old was Alan Turing when he died?\n",
    "Intermediate answer: Alan Turing was 41 years old when he died.\n",
    "So the final answer is: Muhammad Ali\n",
    "\"\"\"\n",
    "  },\n",
    "  {\n",
    "    \"question\": \"When was the founder of craigslist born?\",\n",
    "    \"answer\":\n",
    "\"\"\"\n",
    "Are follow up questions needed here: Yes.\n",
    "Follow up: Who was the founder of craigslist?\n",
    "Intermediate answer: Craigslist was founded by Craig Newmark.\n",
    "Follow up: When was Craig Newmark born?\n",
    "Intermediate answer: Craig Newmark was born on December 6, 1952.\n",
    "So the final answer is: December 6, 1952\n",
    "\"\"\"\n",
    "  },\n",
    "  {\n",
    "    \"question\": \"Who was the maternal grandfather of George Washington?\",\n",
    "    \"answer\":\n",
    "\"\"\"\n",
    "Are follow up questions needed here: Yes.\n",
    "Follow up: Who was the mother of George Washington?\n",
    "Intermediate answer: The mother of George Washington was Mary Ball Washington.\n",
    "Follow up: Who was the father of Mary Ball Washington?\n",
    "Intermediate answer: The father of Mary Ball Washington was Joseph Ball.\n",
    "So the final answer is: Joseph Ball\n",
    "\"\"\"\n",
    "  },\n",
    "  {\n",
    "    \"question\": \"Are both the directors of Jaws and Casino Royale from the same country?\",\n",
    "    \"answer\":\n",
    "\"\"\"\n",
    "Are follow up questions needed here: Yes.\n",
    "Follow up: Who is the director of Jaws?\n",
    "Intermediate Answer: The director of Jaws is Steven Spielberg.\n",
    "Follow up: Where is Steven Spielberg from?\n",
    "Intermediate Answer: The United States.\n",
    "Follow up: Who is the director of Casino Royale?\n",
    "Intermediate Answer: The director of Casino Royale is Martin Campbell.\n",
    "Follow up: Where is Martin Campbell from?\n",
    "Intermediate Answer: New Zealand.\n",
    "So the final answer is: No\n",
    "\"\"\"\n",
    "  }\n",
    "]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:36:02.303782Z",
     "end_time": "2023-08-09T21:36:13.761665Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: Who lived longer, Muhammad Ali or Alan Turing?\n",
      "\n",
      "Are follow up questions needed here: Yes.\n",
      "Follow up: How old was Muhammad Ali when he died?\n",
      "Intermediate answer: Muhammad Ali was 74 years old when he died.\n",
      "Follow up: How old was Alan Turing when he died?\n",
      "Intermediate answer: Alan Turing was 41 years old when he died.\n",
      "So the final answer is: Muhammad Ali\n",
      "\n"
     ]
    }
   ],
   "source": [
    "\n",
    "#配置一个格式化程序，该格式化程序将几个镜头示例格式化为字符串。此格式化程序应该是一个 PromptTemplate 对象。\n",
    "example_prompt = PromptTemplate(input_variables=[\"question\", \"answer\"], template=\"Question: {question}\\n{answer}\")\n",
    "\n",
    "print(example_prompt.format(**examples[0]))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:36:36.222498Z",
     "end_time": "2023-08-09T21:36:36.299905Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: Who lived longer, Muhammad Ali or Alan Turing?\n",
      "\n",
      "Are follow up questions needed here: Yes.\n",
      "Follow up: How old was Muhammad Ali when he died?\n",
      "Intermediate answer: Muhammad Ali was 74 years old when he died.\n",
      "Follow up: How old was Alan Turing when he died?\n",
      "Intermediate answer: Alan Turing was 41 years old when he died.\n",
      "So the final answer is: Muhammad Ali\n",
      "\n",
      "\n",
      "Question: When was the founder of craigslist born?\n",
      "\n",
      "Are follow up questions needed here: Yes.\n",
      "Follow up: Who was the founder of craigslist?\n",
      "Intermediate answer: Craigslist was founded by Craig Newmark.\n",
      "Follow up: When was Craig Newmark born?\n",
      "Intermediate answer: Craig Newmark was born on December 6, 1952.\n",
      "So the final answer is: December 6, 1952\n",
      "\n",
      "\n",
      "Question: Who was the maternal grandfather of George Washington?\n",
      "\n",
      "Are follow up questions needed here: Yes.\n",
      "Follow up: Who was the mother of George Washington?\n",
      "Intermediate answer: The mother of George Washington was Mary Ball Washington.\n",
      "Follow up: Who was the father of Mary Ball Washington?\n",
      "Intermediate answer: The father of Mary Ball Washington was Joseph Ball.\n",
      "So the final answer is: Joseph Ball\n",
      "\n",
      "\n",
      "Question: Are both the directors of Jaws and Casino Royale from the same country?\n",
      "\n",
      "Are follow up questions needed here: Yes.\n",
      "Follow up: Who is the director of Jaws?\n",
      "Intermediate Answer: The director of Jaws is Steven Spielberg.\n",
      "Follow up: Where is Steven Spielberg from?\n",
      "Intermediate Answer: The United States.\n",
      "Follow up: Who is the director of Casino Royale?\n",
      "Intermediate Answer: The director of Casino Royale is Martin Campbell.\n",
      "Follow up: Where is Martin Campbell from?\n",
      "Intermediate Answer: New Zealand.\n",
      "So the final answer is: No\n",
      "\n",
      "\n",
      "Question: Who was the father of Mary Ball Washington?\n"
     ]
    }
   ],
   "source": [
    "#我们可以使用FewShotPromptTemplate来创建一个提示词模板，该模板将输入变量作为输入，并将其格式化为包含示例的提示词。\n",
    "prompt = FewShotPromptTemplate(\n",
    "    examples=examples,\n",
    "    example_prompt=example_prompt,\n",
    "    suffix=\"Question: {input}\",\n",
    "    input_variables=[\"input\"]\n",
    ")\n",
    "\n",
    "print(prompt.format(input=\"Who was the father of Mary Ball Washington?\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:37:47.623899Z",
     "end_time": "2023-08-09T21:37:47.665900Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 3.1.3.1 使用例子选择器\n",
    "\n",
    "在上面的例子中，我们使用了一个简单的例子选择器，它只是返回全部的例子。但是，我们可以使用自定义的例子选择器来选择例子。例如，我们可以使用一个例子选择器，该选择器将选择与输入最相似的例子。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Examples most similar to the input: Who was the father of Mary Ball Washington?\n",
      "\n",
      "\n",
      "answer: \n",
      "Are follow up questions needed here: Yes.\n",
      "Follow up: Who was the mother of George Washington?\n",
      "Intermediate answer: The mother of George Washington was Mary Ball Washington.\n",
      "Follow up: Who was the father of Mary Ball Washington?\n",
      "Intermediate answer: The father of Mary Ball Washington was Joseph Ball.\n",
      "So the final answer is: Joseph Ball\n",
      "\n",
      "question: Who was the maternal grandfather of George Washington?\n"
     ]
    }
   ],
   "source": [
    "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n",
    "from langchain.vectorstores import Chroma\n",
    "from langchain.embeddings import OpenAIEmbeddings\n",
    "#设置代理\n",
    "import os\n",
    "os.environ['http_proxy'] = 'http://127.0.0.1:10809'\n",
    "os.environ['https_proxy'] = 'http://127.0.0.1:10809'\n",
    "\n",
    "example_selector = SemanticSimilarityExampleSelector.from_examples(\n",
    "    # This is the list of examples available to select from.\n",
    "    #zh:这是可供选择的示例列表。\n",
    "    examples,\n",
    "    # This is the embedding class used to produce embeddings which are used to measure semantic similarity.\n",
    "    #zh:这是用于生成嵌入的嵌入类，这些嵌入用于测量语义相似性。\n",
    "    OpenAIEmbeddings(),\n",
    "    # This is the VectorStore class that is used to store the embeddings and do a similarity search over.\n",
    "    #zh:这是用于存储嵌入并进行相似性搜索的 VectorStore 类。\n",
    "    Chroma,\n",
    "    # This is the number of examples to produce.\n",
    "    #zh:这是要生成的示例数。\n",
    "    k=1\n",
    ")\n",
    "\n",
    "# Select the most similar example to the input.\n",
    "#zh:选择与输入最相似的示例。\n",
    "question = \"Who was the father of Mary Ball Washington?\"\n",
    "selected_examples = example_selector.select_examples({\"question\": question})\n",
    "print(f\"Examples most similar to the input: {question}\")\n",
    "for example in selected_examples:\n",
    "    print(\"\\n\")\n",
    "    for k, v in example.items():\n",
    "        print(f\"{k}: {v}\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:44:53.275383Z",
     "end_time": "2023-08-09T21:44:55.222817Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: Who was the maternal grandfather of George Washington?\n",
      "\n",
      "Are follow up questions needed here: Yes.\n",
      "Follow up: Who was the mother of George Washington?\n",
      "Intermediate answer: The mother of George Washington was Mary Ball Washington.\n",
      "Follow up: Who was the father of Mary Ball Washington?\n",
      "Intermediate answer: The father of Mary Ball Washington was Joseph Ball.\n",
      "So the final answer is: Joseph Ball\n",
      "\n",
      "\n",
      "Question: Who was the father of Mary Ball Washington?\n"
     ]
    }
   ],
   "source": [
    "#我们可以使用 FewShotPromptTemplate 来创建一个提示词模板，该模板将输入变量作为输入，并将其格式化为包含示例的提示词。\n",
    "prompt = FewShotPromptTemplate(\n",
    "    example_selector=example_selector,\n",
    "    example_prompt=example_prompt,\n",
    "    suffix=\"Question: {input}\",\n",
    "    input_variables=[\"input\"]\n",
    ")\n",
    "\n",
    "print(prompt.format(input=\"Who was the father of Mary Ball Washington?\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:45:07.942501Z",
     "end_time": "2023-08-09T21:45:08.384402Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 3.1.3.2 带例子的聊天提示词模板"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Human: 2+2\n",
      "AI: 4\n",
      "Human: 2+3\n",
      "AI: 5\n"
     ]
    }
   ],
   "source": [
    "from langchain.prompts import (\n",
    "    FewShotChatMessagePromptTemplate,\n",
    "    ChatPromptTemplate,\n",
    ")\n",
    "\n",
    "#zh:这是一个聊天提示词模板，它将输入变量作为输入，并将其格式化为包含示例的提示词。\n",
    "examples = [\n",
    "    {\"input\": \"2+2\", \"output\": \"4\"},\n",
    "    {\"input\": \"2+3\", \"output\": \"5\"},\n",
    "]\n",
    "\n",
    "# This is a prompt template used to format each individual example.\n",
    "# zh:这是一个提示词模板，用于格式化每个单独的示例。\n",
    "example_prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"human\", \"{input}\"),\n",
    "        (\"ai\", \"{output}\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "few_shot_prompt = FewShotChatMessagePromptTemplate(\n",
    "    example_prompt=example_prompt,\n",
    "    examples=examples,\n",
    ")\n",
    "\n",
    "print(few_shot_prompt.format())"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:50:12.150041Z",
     "end_time": "2023-08-09T21:50:12.244562Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "data": {
      "text/plain": "AIMessage(content='A triangle does not have a square because a square is a specific type of quadrilateral with all sides of equal length and all angles of 90 degrees.', additional_kwargs={}, example=False)"
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#最后，组装您的最终提示并将其与模型一起使用。\n",
    "final_prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"system\", \"You are wonderous wizard of math.\"),\n",
    "        few_shot_prompt,\n",
    "        (\"human\", \"{input}\"),\n",
    "    ]\n",
    ")\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "\n",
    "chain = final_prompt | ChatOpenAI()\n",
    "\n",
    "chain.invoke({\"input\": \"What's the square of a triangle?\"})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:52:50.364975Z",
     "end_time": "2023-08-09T21:52:52.631470Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "#### 3.1.3.3 使用例子选择器的聊天提示词模板\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [],
   "source": [
    "from langchain.prompts import SemanticSimilarityExampleSelector\n",
    "from langchain.embeddings import OpenAIEmbeddings\n",
    "from langchain.vectorstores import Chroma\n",
    "\n",
    "\n",
    "examples = [\n",
    "    {\"input\": \"2+2\", \"output\": \"4\"},\n",
    "    {\"input\": \"2+3\", \"output\": \"5\"},\n",
    "    {\"input\": \"2+4\", \"output\": \"6\"},\n",
    "    {\"input\": \"What did the cow say to the moon?\", \"output\": \"nothing at all\"},\n",
    "    {\n",
    "        \"input\": \"Write me a poem about the moon\",\n",
    "        \"output\": \"One for the moon, and one for me, who are we to talk about the moon?\",\n",
    "    },\n",
    "]\n",
    "\n",
    "#由于我们使用向量存储来根据语义相似性选择示例，因此我们需要首先填充存储。\n",
    "to_vectorize = [\" \".join(example.values()) for example in examples]\n",
    "embeddings = OpenAIEmbeddings()\n",
    "vectorstore = Chroma.from_texts(to_vectorize, embeddings, metadatas=examples)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:54:35.734473Z",
     "end_time": "2023-08-09T21:54:36.601341Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "data": {
      "text/plain": "['2+2 4',\n '2+3 5',\n '2+4 6',\n 'What did the cow say to the moon? nothing at all',\n 'Write me a poem about the moon One for the moon, and one for me, who are we to talk about the moon?']"
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "to_vectorize"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:54:38.371634Z",
     "end_time": "2023-08-09T21:54:38.418056Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [
    {
     "data": {
      "text/plain": "[Document(page_content='What did the cow say to the moon? nothing at all', metadata={'input': 'What did the cow say to the moon?', 'output': 'nothing at all'}),\n Document(page_content='Write me a poem about the moon One for the moon, and one for me, who are we to talk about the moon?', metadata={'input': 'Write me a poem about the moon', 'output': 'One for the moon, and one for me, who are we to talk about the moon?'}),\n Document(page_content='2+2 4', metadata={'input': '2+2', 'output': '4'}),\n Document(page_content='2+4 6', metadata={'input': '2+4', 'output': '6'})]"
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vectorstore.search('cow say to the moon', search_type='similarity')"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:56:38.688423Z",
     "end_time": "2023-08-09T21:56:39.562681Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "data": {
      "text/plain": "[{'input': 'What did the cow say to the moon?', 'output': 'nothing at all'},\n {'input': '2+4', 'output': '6'}]"
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#创建向量库后，可以创建 example_selector .在这里，我们将不建议仅获取前 2 个示例。\n",
    "example_selector = SemanticSimilarityExampleSelector(\n",
    "    vectorstore=vectorstore,\n",
    "    k=2,\n",
    ")\n",
    "\n",
    "# The prompt template will load examples by passing the input do the `select_examples` method\n",
    "# zh:提示词模板将通过将输入传递给 `select_examples` 方法来加载示例\n",
    "example_selector.select_examples({\"input\": \"horse\"})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:57:23.110461Z",
     "end_time": "2023-08-09T21:57:24.222458Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [],
   "source": [
    "#最后，我们可以使用 FewShotChatMessagePromptTemplate 来创建一个提示词模板，该模板将输入变量作为输入，并将其格式化为包含示例的提示词。\n",
    "#使用上面 example_selector 创建的模板组装提示模板。\n",
    "from langchain.prompts import (\n",
    "    FewShotChatMessagePromptTemplate,\n",
    "    ChatPromptTemplate,\n",
    ")\n",
    "\n",
    "# Define the few-shot prompt.\n",
    "#zh:定义少量提示。\n",
    "few_shot_prompt = FewShotChatMessagePromptTemplate(\n",
    "    # The input variables select the values to pass to the example_selector\n",
    "    #zh:输入变量选择要传递给 example_selector 的值\n",
    "    input_variables=[\"input\"],\n",
    "    example_selector=example_selector,\n",
    "    # Define how each example will be formatted.\n",
    "    #zh:定义每个示例的格式。\n",
    "    # In this case, each example will become 2 messages:\n",
    "    #zh:在这种情况下，每个示例将成为 2 条消息：\n",
    "    # 1 human, and 1 AI\n",
    "    #zh:1 人类和 1 人工智能\n",
    "    example_prompt=ChatPromptTemplate.from_messages(\n",
    "        [(\"human\", \"{input}\"), (\"ai\", \"{output}\")]\n",
    "    ),\n",
    ")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:58:22.379425Z",
     "end_time": "2023-08-09T21:58:22.390423Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Human: 2+3\n",
      "AI: 5\n",
      "Human: 2+2\n",
      "AI: 4\n"
     ]
    }
   ],
   "source": [
    "#最后，组装您的最终提示并将其与模型一起使用。\n",
    "\n",
    "final_prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"system\", \"You are wonderous wizard of math.\"),\n",
    "        few_shot_prompt,\n",
    "        (\"human\", \"{input}\"),\n",
    "    ]\n",
    ")\n",
    "print(few_shot_prompt.format(input=\"What's 3+3?\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T21:59:51.640730Z",
     "end_time": "2023-08-09T21:59:52.094841Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "data": {
      "text/plain": "AIMessage(content='3 + 3 equals 6.', additional_kwargs={}, example=False)"
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "\n",
    "chain = final_prompt | ChatOpenAI(temperature=0.0)\n",
    "\n",
    "chain.invoke({\"input\": \"What's 3+3?\"})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T22:00:06.574368Z",
     "end_time": "2023-08-09T22:00:07.967204Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1.4 模板格式"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## jinja2 vs f-string\n",
    "\n",
    "### f-string（Python 3.6+）\n",
    "\n",
    "f-string 是 Python 3.6 以后版本中引入的一种新特性，用于在字符串中插入表达式的值。\n",
    "\n",
    "- **语法简洁**：f-string 使用花括号 `{}` 来包裹变量或表达式，并可以在其中执行简单的运算。\n",
    "- **性能较好**：与其他字符串格式化方法相比，f-string 通常有更好的性能。\n",
    "- **仅限于 Python**：f-string 是 Python 的特定功能，不适用于其他编程语言。\n",
    "\n",
    "```python\n",
    "name = \"Alice\"\n",
    "age = 30\n",
    "print(f\"Hello, {name}! You are {age} years old.\")\n",
    "```\n",
    "\n",
    "### jinja2\n",
    "\n",
    "jinja2 是一个流行的模板引擎，常用于网页开发，特别是与 Flask 和 Django 等框架结合使用。\n",
    "\n",
    "- **功能强大**：jinja2 不仅支持变量替换，还提供了许多控制结构（例如循环和条件语句）以及自定义过滤器和宏等高级功能。\n",
    "- **可在多种语境下使用**：虽然 jinja2 通常用于 web 开发，但也可以用于其他需要模板功能的场合。\n",
    "- **需要额外库**：与 f-string 不同，使用 jinja2 需要安装相应的库。\n",
    "\n",
    "```jinja2\n",
    "{% for item in items %}\n",
    "  {{ item.name }}: {{ item.price | currency }}\n",
    "{% endfor %}\n",
    "```\n",
    "\n",
    "总结：\n",
    "如果你只需要基本的字符串插值和格式化，f-string 可能是更好的选择，因为它的语法简洁且无需额外依赖。\n",
    "如果你需要更复杂的模板功能（例如循环、条件、自定义过滤器等），jinja2 可能更合适。\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "data": {
      "text/plain": "'Tell me a funny joke about chickens'"
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#要使用 jinja2 模板：\n",
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "jinja2_template = \"Tell me a {{ adjective }} joke about {{ content }}\"\n",
    "prompt = PromptTemplate.from_template(jinja2_template, template_format=\"jinja2\")\n",
    "\n",
    "prompt.format(adjective=\"funny\", content=\"chickens\")\n",
    "# Output: Tell me a funny joke about chickens."
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T23:36:43.936665Z",
     "end_time": "2023-08-09T23:36:53.592007Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "data": {
      "text/plain": "'Tell me a funny joke about chickens'"
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#要使用 Python f 字符串模板，请执行以下操作：\n",
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "fstring_template = \"\"\"Tell me a {adjective} joke about {content}\"\"\"\n",
    "prompt = PromptTemplate.from_template(fstring_template)\n",
    "\n",
    "prompt.format(adjective=\"funny\", content=\"chickens\")\n",
    "# Output: Tell me a funny joke about chickens."
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T23:37:03.737216Z",
     "end_time": "2023-08-09T23:37:03.782212Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1.5 MessagePromptTemplate的类型"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "LangChain提供不同类型的 MessagePromptTemplate .最常用的是 AIMessagePromptTemplate 和 SystemMessagePromptTemplate HumanMessagePromptTemplate ，它们分别创建 AI 消息、系统消息和人类消息。\n",
    "但是，如果聊天模型支持使用任意角色接收聊天消息，则可以使用 ChatMessagePromptTemplate ，它允许用户指定角色名称。"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "data": {
      "text/plain": "ChatMessage(content='May the force be with you', additional_kwargs={}, role='Jedi')"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.prompts import ChatMessagePromptTemplate\n",
    "\n",
    "prompt = \"May the {subject} be with you\"\n",
    "\n",
    "chat_message_prompt = ChatMessagePromptTemplate.from_template(role=\"Jedi\", template=prompt)\n",
    "chat_message_prompt.format(subject=\"force\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T23:39:59.945956Z",
     "end_time": "2023-08-09T23:40:00.063472Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [],
   "source": [
    "#LangChain 还提供了 MessagesPlaceholder ，它使您可以完全控制在格式化过程中要呈现的消息。\n",
    "# 当您不确定应为邮件提示模板使用什么角色时，或者当您希望在格式化过程中插入邮件列表时，这可能很有用。\n",
    "from langchain.prompts import MessagesPlaceholder,HumanMessagePromptTemplate,ChatPromptTemplate\n",
    "\n",
    "human_prompt = \"Summarize our conversation so far in {word_count} words.\"\n",
    "human_message_template = HumanMessagePromptTemplate.from_template(human_prompt)\n",
    "\n",
    "chat_prompt = ChatPromptTemplate.from_messages([MessagesPlaceholder(variable_name=\"conversation\"), human_message_template])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T23:41:24.658530Z",
     "end_time": "2023-08-09T23:41:24.685524Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "data": {
      "text/plain": "[HumanMessage(content='What is the best way to learn programming?', additional_kwargs={}, example=False),\n AIMessage(content='1. Choose a programming language: Decide on a programming language that you want to learn.\\n\\n2. Start with the basics: Familiarize yourself with the basic programming concepts such as variables, data types and control structures.\\n\\n3. Practice, practice, practice: The best way to learn programming is through hands-on experience', additional_kwargs={}, example=False),\n HumanMessage(content='Summarize our conversation so far in 10 words.', additional_kwargs={}, example=False)]"
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.schema import HumanMessage,AIMessage\n",
    "human_message = HumanMessage(content=\"What is the best way to learn programming?\")\n",
    "ai_message = AIMessage(content=\"\"\"\\\n",
    "1. Choose a programming language: Decide on a programming language that you want to learn.\n",
    "\n",
    "2. Start with the basics: Familiarize yourself with the basic programming concepts such as variables, data types and control structures.\n",
    "\n",
    "3. Practice, practice, practice: The best way to learn programming is through hands-on experience\\\n",
    "\"\"\")\n",
    "\n",
    "chat_prompt.format_prompt(conversation=[human_message, ai_message], word_count=\"10\").to_messages()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-09T23:43:14.224248Z",
     "end_time": "2023-08-09T23:43:14.268124Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1.6 部分提示模板"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "foobaz\n"
     ]
    }
   ],
   "source": [
    "# 带字符串的部分\n",
    "\n",
    "from langchain.prompts import PromptTemplate\n",
    "prompt = PromptTemplate(template=\"{foo}{bar}\", input_variables=[\"foo\", \"bar\"])\n",
    "# 您可以使用 PromptTemplate.partial() 方法创建部分提示模板。\n",
    "partial_prompt = prompt.partial(foo=\"foo\")\n",
    "print(partial_prompt.format(bar=\"baz\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T20:46:15.174745Z",
     "end_time": "2023-08-10T20:46:27.589876Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "foobaz\n"
     ]
    }
   ],
   "source": [
    "#您也可以只使用分部变量初始化提示。\n",
    "prompt = PromptTemplate(template=\"{foo}{bar}\", input_variables=[\"bar\"], partial_variables={\"foo\": \"foo\"})\n",
    "print(prompt.format(bar=\"baz\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T20:46:40.603439Z",
     "end_time": "2023-08-10T20:46:40.661944Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tell me a funny joke about the day 08/10/2023, 20:51:28\n"
     ]
    }
   ],
   "source": [
    "# 部分带函数\n",
    "\n",
    "#另一个常见用途是部分使用函数。这样做的用例是，当您知道有一个变量时，您总是希望以通用方式获取。\n",
    "# 一个典型的例子是日期或时间。想象一下，您有一个提示，您始终希望具有当前日期。\n",
    "# 您无法在提示中对其进行硬编码，并且将其与其他输入变量一起传递有点烦人。\n",
    "# 在这种情况下，能够使用始终返回当前日期的函数来部分提示非常方便。\n",
    "\n",
    "from datetime import datetime\n",
    "\n",
    "def _get_datetime():\n",
    "    now = datetime.now()\n",
    "    return now.strftime(\"%m/%d/%Y, %H:%M:%S\")\n",
    "\n",
    "prompt = PromptTemplate(\n",
    "    template=\"Tell me a {adjective} joke about the day {date}\",\n",
    "    input_variables=[\"adjective\", \"date\"]\n",
    ")\n",
    "partial_prompt = prompt.partial(date=_get_datetime)\n",
    "print(partial_prompt.format(adjective=\"funny\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T20:51:28.489031Z",
     "end_time": "2023-08-10T20:51:28.571310Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tell me a funny joke about the day 08/10/2023, 20:51:53\n"
     ]
    }
   ],
   "source": [
    "# 您也可以只使用部分变量初始化提示，这在此工作流中通常更有意义。\n",
    "prompt = PromptTemplate(\n",
    "    template=\"Tell me a {adjective} joke about the day {date}\",\n",
    "    input_variables=[\"adjective\"],\n",
    "    partial_variables={\"date\": _get_datetime}\n",
    ")\n",
    "print(prompt.format(adjective=\"funny\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T20:51:53.324239Z",
     "end_time": "2023-08-10T20:51:53.393699Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1.7 组成"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "# 您可以使用 PromptTemplate.compose() 方法将多个提示组合在一起。\n",
    "\n",
    "from langchain.prompts.pipeline import PipelinePromptTemplate\n",
    "from langchain.prompts.prompt import PromptTemplate\n",
    "full_template = \"\"\"{introduction}\n",
    "\n",
    "{example}\n",
    "\n",
    "{start}\"\"\"\n",
    "full_prompt = PromptTemplate.from_template(full_template)\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:14:30.466749Z",
     "end_time": "2023-08-10T21:14:30.511742Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [],
   "source": [
    "introduction_template = \"\"\"You are impersonating {person}.\"\"\"\n",
    "introduction_prompt = PromptTemplate.from_template(introduction_template)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:14:42.474481Z",
     "end_time": "2023-08-10T21:14:42.537491Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [],
   "source": [
    "example_template = \"\"\"Here's an example of an interaction:\n",
    "\n",
    "Q: {example_q}\n",
    "A: {example_a}\"\"\"\n",
    "example_prompt = PromptTemplate.from_template(example_template)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:14:50.529389Z",
     "end_time": "2023-08-10T21:14:50.591570Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "start_template = \"\"\"Now, do this for real!\n",
    "\n",
    "Q: {input}\n",
    "A:\"\"\"\n",
    "start_prompt = PromptTemplate.from_template(start_template)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:15:00.972464Z",
     "end_time": "2023-08-10T21:15:01.021985Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [],
   "source": [
    "input_prompts = [\n",
    "    (\"introduction\", introduction_prompt),\n",
    "    (\"example\", example_prompt),\n",
    "    (\"start\", start_prompt)\n",
    "]\n",
    "pipeline_prompt = PipelinePromptTemplate(final_prompt=full_prompt, pipeline_prompts=input_prompts)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:15:14.197815Z",
     "end_time": "2023-08-10T21:15:14.258322Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "data": {
      "text/plain": "['example_q', 'input', 'example_a', 'person']"
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pipeline_prompt.input_variables"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:15:25.937712Z",
     "end_time": "2023-08-10T21:15:25.986768Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You are impersonating Elon Musk.\n",
      "\n",
      "Here's an example of an interaction: \n",
      "\n",
      "Q: What's your favorite car?\n",
      "A: Tesla\n",
      "\n",
      "Now, do this for real!\n",
      "\n",
      "Q: What's your favorite social media site?\n",
      "A:\n"
     ]
    }
   ],
   "source": [
    "print(pipeline_prompt.format(\n",
    "    person=\"Elon Musk\",\n",
    "    example_q=\"What's your favorite car?\",\n",
    "    example_a=\"Tesla\",\n",
    "    input=\"What's your favorite social media site?\"\n",
    "))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:15:35.551578Z",
     "end_time": "2023-08-10T21:15:35.648690Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1.8 序列化储存提示词"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [],
   "source": [
    "#通常建议将提示存储为文件，而不是 python 代码。\n",
    "# 这可以轻松共享、存储和版本提示。\n",
    "# 本笔记本介绍了如何在 LangChain 中执行此操作，演练了所有不同类型的提示和不同的序列化选项。\n",
    "# zh: 所有提示都是通过`load_prompt`函数加载的。\n",
    "from langchain.prompts import load_prompt\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:29:54.517323Z",
     "end_time": "2023-08-10T21:29:54.548321Z"
    }
   }
  },
  {
   "cell_type": "raw",
   "source": [],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tell me a funny joke about chickens.\n"
     ]
    }
   ],
   "source": [
    "#这显示了从 YAML 加载提示模板的示例。\n",
    "prompt = load_prompt(\"promptstore/simple_prompt.yaml\")\n",
    "print(prompt.format(adjective=\"funny\", content=\"chickens\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:29:58.130507Z",
     "end_time": "2023-08-10T21:29:58.168676Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tell me a funny joke about chickens.\n"
     ]
    }
   ],
   "source": [
    "#这显示了从 JSON 加载提示模板的示例。\n",
    "prompt = load_prompt(\"promptstore/simple_prompt.json\")\n",
    "print(prompt.format(adjective=\"funny\", content=\"chickens\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:31:03.038833Z",
     "end_time": "2023-08-10T21:31:03.085495Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    Tell me a funny joke about chickens.\n"
     ]
    }
   ],
   "source": [
    "#这显示了将模板存储在单独的文件中，然后在配置中引用它的示例。请注意，键从 template 更改为 template_path 。\n",
    "prompt = load_prompt(\"promptstore/simple_prompt_with_template_file.json\")\n",
    "print(prompt.format(adjective=\"funny\", content=\"chickens\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:32:42.556843Z",
     "end_time": "2023-08-10T21:32:42.571846Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Write antonyms for the following words.\n",
      "\n",
      "Input: happy\n",
      "Output: sad\n",
      "\n",
      "Input: tall\n",
      "Output: short\n",
      "\n",
      "Input: funny\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "#这显示了从 YAML 加载几个镜头示例的示例。\n",
    "prompt = load_prompt(\"promptstore/few_shot_prompt.yaml\")\n",
    "print(prompt.format(adjective=\"funny\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:43:18.601472Z",
     "end_time": "2023-08-10T21:43:18.611473Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Write antonyms for the following words.\n",
      "\n",
      "Input: happy\n",
      "Output: sad\n",
      "\n",
      "Input: tall\n",
      "Output: short\n",
      "\n",
      "Input: funny\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "#如果您从 yaml 文件加载示例，这同样有效。\n",
    "prompt = load_prompt(\"promptstore/few_shot_prompt_yaml_examples.yaml\")\n",
    "print(prompt.format(adjective=\"funny\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:45:11.793155Z",
     "end_time": "2023-08-10T21:45:11.863714Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Write antonyms for the following words.\n",
      "\n",
      "Input: happy\n",
      "Output: sad\n",
      "\n",
      "Input: tall\n",
      "Output: short\n",
      "\n",
      "Input: funny\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "#这显示了从 JSON 加载几个镜头示例的示例。\n",
    "prompt = load_prompt(\"promptstore/few_shot_prompt.json\")\n",
    "print(prompt.format(adjective=\"funny\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:46:04.201785Z",
     "end_time": "2023-08-10T21:46:04.267229Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Write antonyms for the following words.\n",
      "\n",
      "Input: happy\n",
      "Output: sad\n",
      "\n",
      "Input: tall\n",
      "Output: short\n",
      "\n",
      "Input: funny\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "#这显示了直接在配置中引用示例的示例。\n",
    "prompt = load_prompt(\"promptstore/few_shot_prompt_examples_in.json\")\n",
    "print(prompt.format(adjective=\"funny\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:46:49.188001Z",
     "end_time": "2023-08-10T21:46:49.275132Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Write antonyms for the following words.\n",
      "\n",
      "Input: happy\n",
      "Output: sad\n",
      "\n",
      "Input: tall\n",
      "Output: short\n",
      "\n",
      "Input: funny\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "#这显示了加载用于从单独文件设置示例格式的提示模板的示例。请注意，密钥从 更改为 example_prompt example_prompt_path\n",
    "prompt = load_prompt(\"promptstore/few_shot_prompt_example_prompt.json\")\n",
    "print(prompt.format(adjective=\"funny\"))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:48:20.811962Z",
     "end_time": "2023-08-10T21:48:20.913477Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1.9 提示流水线"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "outputs": [
    {
     "data": {
      "text/plain": "PromptTemplate(input_variables=['topic', 'language'], output_parser=None, partial_variables={}, template='Tell me a joke about {topic}, make it funny\\n\\nand in {language}', template_format='f-string', validate_template=True)"
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#提示流水线背后的想法是公开一个用户友好的界面，用于将提示的不同部分组合在一起。\n",
    "# 您可以使用字符串提示或聊天提示来执行此操作。以这种方式构造提示允许轻松重用组件。\n",
    "\n",
    "# 使用字符串提示时，每个模板都联接在一起。可以直接使用提示或字符串（列表中的第一个元素必须是提示）。\n",
    "from langchain.prompts import PromptTemplate\n",
    "prompt = (\n",
    "    PromptTemplate.from_template(\"Tell me a joke about {topic}\")\n",
    "    + \", make it funny\"\n",
    "    + \"\\n\\nand in {language}\"\n",
    ")\n",
    "prompt"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:50:03.706338Z",
     "end_time": "2023-08-10T21:50:03.765633Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "outputs": [
    {
     "data": {
      "text/plain": "'Tell me a joke about sports, make it funny\\n\\nand in spanish'"
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用聊天提示时，每个模板都是一个单独的步骤。可以直接使用提示或字符串（列表中的第一个元素必须是提示）。\n",
    "prompt.format(topic=\"sports\", language=\"spanish\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:50:33.866955Z",
     "end_time": "2023-08-10T21:50:33.919547Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "outputs": [
    {
     "data": {
      "text/plain": "'为什么足球队的草皮总是那么干燥？\\n\\n因为球员总是把球“踢”走！(为了保持诙谐效果，请注意这个笑话的发音)\\n\\nTranslation: Why is the football field always so dry?\\n\\nBecause the players keep \"kicking\" the ball away!'"
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 您也可以像以前一样在LLMChain中使用它。\n",
    "#设置代理\n",
    "import os\n",
    "os.environ['http_proxy'] = 'http://127.0.0.1:10809'\n",
    "os.environ['https_proxy'] = 'http://127.0.0.1:10809'\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.chains import LLMChain\n",
    "model = ChatOpenAI()\n",
    "chain = LLMChain(llm=model, prompt=prompt)\n",
    "chain.run(topic=\"sports\", language=\"chinese\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:52:41.845275Z",
     "end_time": "2023-08-10T21:52:45.857202Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "outputs": [
    {
     "data": {
      "text/plain": "[SystemMessage(content='You are a nice pirate', additional_kwargs={}),\n HumanMessage(content='hi', additional_kwargs={}, example=False),\n AIMessage(content='what?', additional_kwargs={}, example=False),\n HumanMessage(content='i said hi', additional_kwargs={}, example=False)]"
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 聊天提示由消息列表组成。纯粹为了获得开发人员体验，我们添加了一种方便的方式来创建这些提示。\n",
    "# 在此管道中，每个新元素都是最终提示符中的新消息。\n",
    "from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate\n",
    "from langchain.schema import HumanMessage, AIMessage, SystemMessage\n",
    "prompt = SystemMessage(content=\"You are a nice pirate\")\n",
    "new_prompt = (\n",
    "    prompt\n",
    "    + HumanMessage(content=\"hi\")\n",
    "    + AIMessage(content=\"what?\")\n",
    "    + \"{input}\"\n",
    ")\n",
    "new_prompt.format_messages(input=\"i said hi\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:54:13.429822Z",
     "end_time": "2023-08-10T21:54:13.487337Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "outputs": [
    {
     "data": {
      "text/plain": "'Hello! How can I help you today?'"
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#您也可以像以前一样在LLMChain中使用它。\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.chains import LLMChain\n",
    "model = ChatOpenAI()\n",
    "chain = LLMChain(llm=model, prompt=new_prompt)\n",
    "chain.run(\"i said hi\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:54:45.689957Z",
     "end_time": "2023-08-10T21:54:46.703911Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 3.1.10 验证模板"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "outputs": [
    {
     "ename": "ValidationError",
     "evalue": "1 validation error for PromptTemplate\n__root__\n  Invalid prompt schema; check for mismatched or missing input parameters. {'foo'} (type=value_error)",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mValidationError\u001B[0m                           Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[34], line 4\u001B[0m\n\u001B[0;32m      1\u001B[0m \u001B[38;5;66;03m#在某些情况下，您可能希望验证模板是否具有正确的变量。\u001B[39;00m\n\u001B[0;32m      2\u001B[0m template \u001B[38;5;241m=\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mI am learning langchain because \u001B[39m\u001B[38;5;132;01m{reason}\u001B[39;00m\u001B[38;5;124m.\u001B[39m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m----> 4\u001B[0m prompt_template \u001B[38;5;241m=\u001B[39m \u001B[43mPromptTemplate\u001B[49m\u001B[43m(\u001B[49m\u001B[43mtemplate\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mtemplate\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m      5\u001B[0m \u001B[43m                                 \u001B[49m\u001B[43minput_variables\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43m[\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mreason\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mfoo\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m)\u001B[49m \u001B[38;5;66;03m# ValueError due to extra variables # zh: 由于额外的变量而导致的 ValueError\u001B[39;00m\n\u001B[0;32m      6\u001B[0m prompt_template \u001B[38;5;241m=\u001B[39m PromptTemplate(template\u001B[38;5;241m=\u001B[39mtemplate,\n\u001B[0;32m      7\u001B[0m                                  input_variables\u001B[38;5;241m=\u001B[39m[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mreason\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mfoo\u001B[39m\u001B[38;5;124m\"\u001B[39m],\n\u001B[0;32m      8\u001B[0m                                  validate_template\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mFalse\u001B[39;00m) \u001B[38;5;66;03m# No error\u001B[39;00m\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\langchain\\load\\serializable.py:74\u001B[0m, in \u001B[0;36mSerializable.__init__\u001B[1;34m(self, **kwargs)\u001B[0m\n\u001B[0;32m     73\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21m__init__\u001B[39m(\u001B[38;5;28mself\u001B[39m, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Any) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[1;32m---> 74\u001B[0m     \u001B[38;5;28msuper\u001B[39m()\u001B[38;5;241m.\u001B[39m\u001B[38;5;21m__init__\u001B[39m(\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)\n\u001B[0;32m     75\u001B[0m     \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_lc_kwargs \u001B[38;5;241m=\u001B[39m kwargs\n",
      "File \u001B[1;32mE:\\pycharmproject\\LangChainStudyProject\\venv\\lib\\site-packages\\pydantic\\main.py:341\u001B[0m, in \u001B[0;36mpydantic.main.BaseModel.__init__\u001B[1;34m()\u001B[0m\n",
      "\u001B[1;31mValidationError\u001B[0m: 1 validation error for PromptTemplate\n__root__\n  Invalid prompt schema; check for mismatched or missing input parameters. {'foo'} (type=value_error)"
     ]
    }
   ],
   "source": [
    "#在某些情况下，您可能希望验证模板是否具有正确的变量。\n",
    "template = \"I am learning langchain because {reason}.\"\n",
    "\n",
    "prompt_template = PromptTemplate(template=template,\n",
    "                                 input_variables=[\"reason\", \"foo\"]) # ValueError due to extra variables # zh: 由于额外的变量而导致的 ValueError"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "outputs": [],
   "source": [
    "prompt_template = PromptTemplate(template=template,\n",
    "                                 input_variables=[\"reason\", \"foo\"],\n",
    "                                 validate_template=False) # No error # zh: 没有错误"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:56:24.963082Z",
     "end_time": "2023-08-10T21:56:25.034081Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "outputs": [
    {
     "data": {
      "text/plain": "PromptTemplate(input_variables=['reason', 'foo'], output_parser=None, partial_variables={}, template='I am learning langchain because {reason}.', template_format='f-string', validate_template=False)"
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt_template"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-10T21:56:30.333477Z",
     "end_time": "2023-08-10T21:56:30.423996Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
